package com.zxy.intercept;

import com.zxy.model.BaseModel;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;

import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.statement.update.UpdateSet;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;

//语句拦截器
@Component
@Slf4j
//F9 走到下一个断点
//F8 下一步
//F7 进入方法内部
@Intercepts(@Signature(type = StatementHandler.class,method = "prepare",args = {Connection.class,Integer.class}))
public class StatementPlugin implements Interceptor {
    private static final String LAST_UPDATE_BY = "lastUpdateBy";
    //    核心 intercept
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
       StatementHandler statementHandler = (StatementHandler) invocation.getTarget();

        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
        MappedStatement ms = (MappedStatement)metaObject.getValue("delegate.mappedStatement");
//对象和相关sql的语句都在MappedStatement里面
        BoundSql boundSql = statementHandler.getBoundSql();

        Object parameterObject = boundSql.getParameterObject();
        if (parameterObject instanceof BaseModel){
//            增强
            String sql = boundSql.getSql();
            List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
            SqlCommandType commandType = ms.getSqlCommandType();

            if (commandType == SqlCommandType.INSERT){
                Insert insert = (Insert) CCJSqlParserUtil.parse(sql);

//                添加列字段
                insert.addColumns(new Column(LAST_UPDATE_BY));
//                添加一个占位符
                ExpressionList itemsList = insert.getItemsList(ExpressionList.class);
//                List<Expression> expressions = itemsList.getExpressions();
//                itemsList.addExpressions(new JdbcParameter());
                itemsList.getExpressions().add(new JdbcParameter());

//                添加映射关系
                List<ParameterMapping> collect= parameterMappings.stream().filter(p->p.getProperty().equals(LAST_UPDATE_BY)).collect(Collectors.toList());
                if(collect.size() == 0){
                    parameterMappings.add(new ParameterMapping.Builder(ms.getConfiguration(),LAST_UPDATE_BY,String.class).build());
                }
                metaObject.setValue("delegate.boundSql.sql",insert.toString());

//                Table table = insert.getTable();
//                log.debug("表{}新增数据",table);

            } else if (commandType == SqlCommandType.UPDATE) {
                Update update = (Update)CCJSqlParserUtil.parse(sql);

                //                添加列字段 同时添加一个占位符
                update.getUpdateSets().add(new UpdateSet(new Column(LAST_UPDATE_BY),new JdbcParameter()));
//                ArrayList<UpdateSet> updateSets = update.getUpdateSets();
//                updateSets.add(new UpdateSet(new Column(LAST_UPDATE_BY),new JdbcParameter()));
//                update.addColumns(new Column(LAST_UPDATE_BY));
//                添加一个占位符
//                ExpressionList itemsList = update.getItemsList(ExpressionList.class);
//                itemsList.getExpressions().add(new JdbcParameter());

//                添加映射关系
                parameterMappings.add(
                        parameterMappings.size()-1,
                        new ParameterMapping.Builder(ms.getConfiguration(),LAST_UPDATE_BY,String.class).build());
                metaObject.setValue("delegate.boundSql.sql",update.toString());
                String mm = "";

//                Table table = update.getTable();
//                log.debug("表{}修改数据",table);
            }
            String mm = "";
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }

    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }
}
